﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIObjects.TreeViewInterfaces;
using AbstraX.ClientInterfaces;
using System.Collections.ObjectModel;
using TreeBuilder.Contracts;
using MvvmTreeView;
using System.Windows.Controls;
using System.Diagnostics;
using SL4PopupMenu;
using System.Windows;

namespace TreeBuilder.ViewModels
{
    public class TreeBuilderTreeNodeMenuItem : TreeBuilderTreeNodeImageNode
    {
        private ITreeNodeMenuItem menuItem;
        private bool allowDrop;

        public TreeBuilderTreeNodeMenuItem(ITreeBuilderService treeBuilderService, ITreeView treeView, ITreeNodeMenuItem menuItem, ITreeNode parent) : base(treeBuilderService, treeView, parent)
        {
            this.menuItem = menuItem;
            this.Tag = menuItem;
            this.allowDrop = true;

            this.menuItem.ImageAvailable += new ImageNodeImageAvailableHandler(NotifyImageAvailable);
        }

        public override ITreeNodeImage TreeNodeImage
        {
            get
            {
                return this.menuItem.TreeNodeImage;
            }

            set
            {
                this.menuItem.TreeNodeImage = value;
            }
        }

        public override ITreeNodeBase InternalNodeObject
        {
            get
            {
                return menuItem;
            }
        }

        public override IBase BaseObject
        {
            get
            {
                return menuItem.MenuSource;
            }
            set
            {
                menuItem.MenuSource = value;
            }
        }

        public override void Expand()
        {
            if (!this.IsChildrenLoaded)
            {
                menuItem.ChildrenLoaded += new TreeBuilder.Contracts.ChildrenLoadedHandler(OnChildrenLoaded);
                menuItem.LoadChildren();
            }

            base.Expand();
        }

        public override string Text
        {
            get
            {
                return menuItem.Text;
            }

            set
            {
                menuItem.Text = value;
            }
        }

        public void AddSubMenu(object sender, RoutedEventArgs r)
        {
            var createOperation = treeBuilderService.CreateMenuItem(menuItem, this.BaseObject);

            createOperation.NodeCreated += (parent, e) =>
            {
                this.Nodes.Add(new TreeBuilderTreeNodeMenuItem(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                base.Expand();
            };
        }

        public void AddOperationMenu(IOperation operation)
        {
            var createOperation = treeBuilderService.CreateMenuItem(menuItem, this.BaseObject, operation);

            createOperation.NodeCreated += (parent, e) =>
            {
                this.Nodes.Add(new TreeBuilderTreeNodeMenuItem(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                base.Expand();
            };

        }

        public void AddStockActionMenu(TreeNodeMenuItemStockAction stockAction, StockActionMenuAttribute stockActionMenuAttribute)
        {
            var createOperation = treeBuilderService.CreateMenuItem(menuItem, this.BaseObject, stockAction);

            createOperation.NodeCreated += (parent, e) =>
            {
                this.Nodes.Add(new TreeBuilderTreeNodeMenuItem(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                base.Expand();

                if (stockActionMenuAttribute.SpecialStockActionMenu != null)
                {
                    Debugger.Break();
                }
            };
        }

        private List<IContextMenuItem> GetStockActionMenus()
        {
            var subMenus = new List<IContextMenuItem>();

            foreach (var field in typeof(TreeNodeMenuItemStockAction).GetFields())
            {
                if ((field.Attributes & System.Reflection.FieldAttributes.Static) > 0)
                {
                    var stockActionMenuAttribute = (StockActionMenuAttribute)field.GetCustomAttributes(typeof(StockActionMenuAttribute), true).Single();
                    var stockAction = (TreeNodeMenuItemStockAction)field.GetValue(null);

                    subMenus.Add(new ContextMenuItem(null, stockActionMenuAttribute.DisplayText, stockActionMenuAttribute.ToString(), (sender, e) =>
                    {
                        AddStockActionMenu(stockAction, stockActionMenuAttribute);
                    }));
                }
            }

            return subMenus;
        }

        private List<IContextMenuItem> GetMenuItemSourceSubMenus()
        {
            List<IContextMenuItem> subMenus = new List<IContextMenuItem>();

            if (this.BaseObject is IElement)
            {
                IElement element = (IElement)this.BaseObject;

                foreach (var childElement in element.ChildElements)
                {
                    if (childElement.DataType.IsCollectionType)
                    {
                        var bindElement = childElement;

                        subMenus.Add(new ContextMenuItem(null, bindElement.Name, bindElement.Name, (sender, e) =>
                        {
                            //AddNodePropertyBinding(TreeNodePropertyType.Children, bindElement);
                        }));
                    }
                }
            }

            subMenus.Add(new ContextMenuItem(null, "Query...", "CreateQueryChildrenValue", (sender, e) =>
            {
                //AddNodePropertyBinding(TreeNodePropertyType.Children, TreeNodePropertyStockBinding.FromQuery);
            }));

            subMenus.Add(new ContextMenuItem(null, "Advanced Query...", "CreateQueryChildrenValue", (sender, e) =>
            {
                //AddNodePropertyBinding(TreeNodePropertyType.Children, TreeNodePropertyStockBinding.FromQuery);
            }));

            return subMenus;
        }
        private List<IContextMenuItem> GetOperationMenus()
        {
            List<IContextMenuItem> subMenus = new List<IContextMenuItem>();

            if (menuItem.MenuSource is IElement)
            {
                IElement element = (IElement)menuItem.MenuSource;

                foreach (var operation in element.Operations)
                {
                    subMenus.Add(new ContextMenuItem(null, operation.Name, operation.Name, (sender, e) =>
                    {
                        AddOperationMenu(operation);
                    }));
                }
            }

            subMenus.Add(new ContextMenuItem(null, "Query", null, AddQuery));
            subMenus.Add(new ContextMenuItem(null, "Advanced Query...", null, AddAdvancedQuery));
        
            return subMenus;
        }

        public override ContextMenu ContextMenu
        {
            get
            {
                if (contextMenu == null)
                {
                    contextMenu = new ContextMenu
                    {
                        Items = new List<IContextMenuItem>()
                        {
                            new ContextMenuItem(null, "Add Sub Menu", null, AddSubMenu),
                            new ContextMenuItem
                            {
                                Text = "Add Stock Menu",
                                Items = GetStockActionMenus()
                            },
                            new ContextMenuItem
                            {
                                Text = "Add Menu Bound To",
                                Items = GetOperationMenus()
                            },
                            new ContextMenuItem
                            {
                                Text = "Add Menu Item Source From",
                                Items = GetMenuItemSourceSubMenus()
                            }
                        }
                    };
                }

                return contextMenu;
            }

            set
            {
                contextMenu = value;
            }
        }

        public override bool? HasChildren
        {
            get { throw new NotImplementedException(); }
        }

        public override string ID
        {
            get 
            {
                return menuItem.ID;
            }
        }

        public override void LoadChildren()
        {
            menuItem.ChildrenLoaded += new TreeBuilder.Contracts.ChildrenLoadedHandler(OnChildrenLoaded);
            menuItem.LoadChildren();
        }

        public override IEnumerable<ITreeNodeBase> Children
        {
            get 
            {
                return menuItem.Children;
            }
        }

        public override void Remove()
        {
            menuItem.RemovedSuccessfully += (node, e) =>
            {
                this.parent.Nodes.Remove(this);

                var op = treeBuilderService.OrphansExist();

                op.Completed += (sender, e2) =>
                {
                    if (op.Value)
                    {
                        MessageBox.Show("Orphans exist!");
                    }
                };
            };

            menuItem.Remove();
        }

        public override bool AllowDrop
        {
            get
            {
                return allowDrop;
            }
            set
            {
                allowDrop = value;
            }
        }

        public override ITreeNode ShallowClone()
        {
            throw new NotImplementedException();
        }

		public override void OnSelect()
		{
		}
        public override ITreeNode DeepClone()
        {
            throw new NotImplementedException();
        }

        public override bool AllowRename
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override void AddNew(string shortCut)
        {
        }

        public override void DragEnter(object sender, UIObjects.DragDropInterfaces.DragEventArgs e)
        {
        }

        public override void DragLeave(object sender, UIObjects.DragDropInterfaces.DragEventArgs e)
        {
        }

        public override void DragOver(object sender, UIObjects.DragDropInterfaces.DragEventArgs e)
        {
        }

        public override void DragStarting(object sender, UIObjects.DragDropInterfaces.ItemDragEventArgs e)
        {
        }

        public override void DragCompleted(object sender, UIObjects.DragDropInterfaces.ItemDragEventArgs e)
        {
        }

        public override void ItemDropped(object sender, UIObjects.DragDropInterfaces.ItemDragEventArgs e, int insertionIndex)
        {
        }

        public override void GiveFeedback(object sender, UIObjects.DragDropInterfaces.GiveFeedbackEventArgs e)
        {
        }

        public override float ChildOrdinal
        {
            get
            {
                return menuItem.ChildOrdinal;
            }
            set
            {
                menuItem.ChildOrdinal = value;
            }
        }
    }
}
